
/**
  ******************************************************************************
  * Copyright 2021 The grapilot Authors. All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * 
  * @file       gp_udp.c
  * @author     baiyang
  * @date       2021-7-18
  ******************************************************************************
  */

/*----------------------------------include-----------------------------------*/
#include "gp_udp.h"
#include <tchar.h>
/*-----------------------------------macro------------------------------------*/

/*----------------------------------typedef-----------------------------------*/

/*---------------------------------prototype----------------------------------*/

/*----------------------------------variable----------------------------------*/

/*-------------------------------------os-------------------------------------*/

/*----------------------------------function----------------------------------*/
MUdpObj::MUdpObj()
{
    memset(m_SrcIP, 0, sizeof(m_SrcIP));
    memset(m_DesIP, 0, sizeof(m_DesIP));

    m_uDesRecvPort = 0;
    m_uSrcSendPort = 0;
    m_uSrcRecvPort = 0;

    m_sockStream = INVALID_SOCKET;

    memset(&m_SendAddr, 0, sizeof(sockaddr_in));
    memset(&m_RecvAddr, 0, sizeof(sockaddr_in));

    Connect = false;
}

MUdpObj::~MUdpObj()
{
    Close();
}

//lpDesIP：目标IP地址  uSrcRecvPort：监听端口号  uDesRecvPort：目标端口号  lpSrcIP：源IP地址  源端口号
BOOL MUdpObj::Init(LPCTSTR lpDesIP, UINT uSrcRecvPort, UINT uDesRecvPort, LPCTSTR lpSrcIP, UINT uSrcSendPort)
{
    //IP地址赋值
    if (lpDesIP != NULL)
    {
        _tcscpy_s(m_DesIP,lpDesIP);
    }

    if (lpSrcIP != NULL)
    {
        _tcscpy_s(m_SrcIP, lpSrcIP);
    }

    //设置端口号
    m_uDesRecvPort = uDesRecvPort;
    m_uSrcSendPort = uSrcSendPort;
    m_uSrcRecvPort = uSrcRecvPort;

    if (m_uDesRecvPort != 0)
    {
        if (_tcscmp(m_DesIP, _T("")) == 0)
        {
            Close();
            return FALSE;
        }

        m_sockStream = socket(AF_INET, SOCK_DGRAM, 0);
        if (m_sockStream == INVALID_SOCKET)
        {
            //socket创建失败
            Close();
            return FALSE;
        }

        m_SendAddr.sin_family = AF_INET;
        m_SendAddr.sin_port = htons(m_uDesRecvPort);
        InetPton(AF_INET, m_DesIP, &m_SendAddr.sin_addr);

        if (m_uSrcSendPort != 0)
        {
            //IP地址为零
            if (_tcscmp(m_SrcIP, _T("")) == 0)
            {
                SOCKADDR_IN local_send;
                local_send.sin_family = AF_INET;
                local_send.sin_port = htons(m_uSrcRecvPort);
                local_send.sin_addr.s_addr = htonl(INADDR_ANY);
                if (bind(m_sockStream, (LPSOCKADDR)&local_send, sizeof(local_send)) == SOCKET_ERROR)
                {
                    Close();
                    return FALSE;
                }
            }
            else
            {
                SOCKADDR_IN local_send;
                local_send.sin_family = AF_INET;
                local_send.sin_port = htons(m_uSrcRecvPort);
                InetPton(AF_INET, m_SrcIP, &local_send.sin_addr);
                if (bind(m_sockStream, (struct sockaddr*)&local_send, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
                {
                    Close();
                    return FALSE;
                }
            }
        }

        timeval tv = { 1, 0 };
        setsockopt(m_sockStream, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(timeval));
    }

    Connect = true;

    return TRUE;
}

int MUdpObj::Send(char* pBuf, int nSize)
{
    if (m_sockStream != INVALID_SOCKET)
    {
        return sendto(m_sockStream, pBuf, nSize, 0, (SOCKADDR *)&m_SendAddr, sizeof(m_SendAddr));
    }
    return 0;
}

int MUdpObj::Recv(char* pBuf, int nSize)
{
    if (m_sockStream != INVALID_SOCKET)
    {
        int nRecvAddrSize = sizeof(m_RecvAddr);
        return recvfrom(m_sockStream, pBuf, nSize,0, (SOCKADDR *)&m_RecvAddr, &nRecvAddrSize);
    }
    return 0;
}

BOOL MUdpObj::Close()
{
    if (m_sockStream != INVALID_SOCKET)
    {
        shutdown(m_sockStream, SD_BOTH);
        closesocket(m_sockStream);
    }

    memset(m_SrcIP, 0, sizeof(m_SrcIP));
    memset(m_DesIP, 0, sizeof(m_DesIP));

    m_uDesRecvPort = 0;
    m_uSrcSendPort = 0;
    m_uSrcRecvPort = 0;

    m_sockStream = INVALID_SOCKET;

    memset(&m_SendAddr, 0, sizeof(m_SendAddr));
    memset(&m_RecvAddr, 0, sizeof(m_RecvAddr));

    Connect = false;

    return TRUE;
}

SOCKET MUdpObj::GetSocket()
{
    return m_sockStream;
}

/*------------------------------------test------------------------------------*/


